package com.bestcem.xm.survey.grpc.service;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.bestcem.xm.survey.controller.vo.SurveyQuotaConditionVo;
import com.bestcem.xm.survey.convert.grpc.SurveyGrpcConvertMapper;
import com.bestcem.xm.survey.entity.*;
import com.bestcem.xm.survey.grpc.v1.services.*;
import com.bestcem.xm.survey.mapper.*;
import com.bestcem.xm.survey.service.SurveyExtParameterService;
import com.bestcem.xm.survey.service.SurveyMessageReceiverService;
import com.bestcem.xm.survey.service.SurveyQuotaConditionService;
import com.bestcem.xm.survey.service.SurveyRespondentService;
import com.google.common.collect.Lists;
import com.google.protobuf.Timestamp;
import io.grpc.stub.StreamObserver;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.server.service.GrpcService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.util.ObjectUtils;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import static com.bestcem.xm.survey.enums.RespondentStatusEnum.*;
import static com.bestcem.xm.survey.grpc.service.GrpcConstant.FAIL_STATUS;
import static com.bestcem.xm.survey.grpc.service.GrpcConstant.SUCCESS_STATUS;
import static com.bestcem.xm.survey.grpc.v1.services.RespondentDataStatus.RESPONDENT_DATA_STATUS_FORMAL_VALUE;
import static com.bestcem.xm.survey.grpc.v1.services.RespondentStatus.RESPONDENT_STATUS_FINISH_VALUE;
import static com.bestcem.xm.survey.util.SurveyConstant.RESPONDENT_FORMAL_SOURCE;

/**
 * 获取基础survey接口
 *
 * @author xiaoshu.shao <xiaoshu.shao@idiaoyan.com>
 * @version V1.0
 * @date 2022/9/21
 */
@GrpcService
@Slf4j
@RequiredArgsConstructor
public class BaseSurveyGrpcService extends BaseSurveyServiceGrpc.BaseSurveyServiceImplBase {
    private final SurveyGrpcConvertMapper grpcConvertMapper;
    private @NonNull SurveyQuotaConditionService surveyQuotaConditionService;
    private @NonNull SurveyQuotaConditionMapper surveyQuotaConditionMapper;
    private @NonNull SurveyQuotaConditionQgidListMapper surveyQuotaConditionQgidListMapper;
    private @NonNull SurveyQuotaCheckItemMapper surveyQuotaCheckItemMapper;
    private @NonNull SurveyQuotaCheckItemOptionCombiesMapper surveyQuotaCheckItemOptionCombiesMapper;
    private @NonNull SurveyQuotaCheckItemOptionListMapper surveyQuotaCheckItemOptionListMapper;
    private @NonNull SurveyRespondentMapper surveyRespondentMapper;
    private @NonNull SurveyRespondentWeixinMapper surveyRespondentWeixinMapper;
    private @NonNull SurveyRespondentQuotaCheckItemMapper surveyRespondentQuotaCheckItemMapper;
    private @NonNull SurveyColumnMapper surveyColumnMapper;
    private @NonNull SurveyRespondentDataMapper surveyRespondentDataMapper;
    private @NonNull SurveyRespondentHashQuestionListMapper surveyRespondentHashQuestionListMapper;
    private @NonNull SurveyExtParameterService surveyExtParameterService;
    private @NonNull SurveyMessageReceiverService surveyMessageReceiverService;
    private @NonNull SurveyRespondentService surveyRespondentService;

    @Override
    public void listQuotaConditionByIds(ListQuotaConditionByIdsRequest request, StreamObserver<QuotaConditionSearchResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now listQuotaConditionByIds");
        QuotaConditionSearchResponse.Builder response = QuotaConditionSearchResponse.newBuilder();
        List<SurveyQuotaConditionVo> quotaConditionVos = surveyQuotaConditionService.getByIds(request.getIdsList());
        List<QuotaCondition> conditions = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(quotaConditionVos)) {
            quotaConditionVos.forEach(conditionVo -> {
                QuotaCondition condition = QuotaCondition.newBuilder()
                        .setName(conditionVo.getName())
                        .setId(conditionVo.getId())
                        .setProjectId(conditionVo.getProjectId())
                        .setQuotaId(conditionVo.getQuotaId())
                        .setCheckpoints(conditionVo.getCheckpoints())
                        .setQgidList(JSONArray.toJSONString(conditionVo.getQgidList()))
                        .setQuotaCheckitemList(JSONArray.toJSONString(conditionVo.getQuotaCheckitemList()))
                        .build();
                conditions.add(condition);
            });
        }
        response.addAllQuotaConditionList(conditions);
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void countQuotaCondition(CountQuotaConditionRequest request, StreamObserver<CountQuotaConditionResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now countQuotaCondition");
        CountQuotaConditionResponse.Builder response = CountQuotaConditionResponse.newBuilder();
        // 这些题目被设置的次数
        LambdaQueryWrapper<SurveyQuotaCondition> sWrapper = new LambdaQueryWrapper<>();
        sWrapper.eq(SurveyQuotaCondition::getProjectId, request.getProjectId());
        List<SurveyQuotaCondition> surveyQuotaConditions = surveyQuotaConditionMapper.selectList(sWrapper);
        if (CollectionUtils.isEmpty(surveyQuotaConditions)) {
            response.setCount(0);
            response.setStatus(SUCCESS_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
            return;
        }
        List<String> quotacondids = surveyQuotaConditions.stream().map(SurveyQuotaCondition::getId).collect(Collectors.toList());
        LambdaQueryWrapper<SurveyQuotaConditionQgidList> qWrapper = new LambdaQueryWrapper<>();
        qWrapper.in(SurveyQuotaConditionQgidList::getQuotaCondId, quotacondids);
        if (CollectionUtils.isNotEmpty(request.getQgidListList())) {
            qWrapper.in(SurveyQuotaConditionQgidList::getQgid, new ArrayList<>(request.getQgidListList()));
        }
        Long aLong = surveyQuotaConditionQgidListMapper.selectCount(qWrapper);
        response.setCount(aLong == null ? 0 : Integer.parseInt(String.valueOf(aLong)));
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void refreshQuotaProgress(RefreshQuotaProgressRequest request, StreamObserver<RefreshQuotaProgressResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now refreshQuotaProgress");
        surveyQuotaConditionService.refreshQuotaProgress(request.getQuotaId());
        RefreshQuotaProgressResponse.Builder response = RefreshQuotaProgressResponse.newBuilder();
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void genQuotaNum(GenQuotaNumRequest request, StreamObserver<GenQuotaNumResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now genQuotaNum");
        surveyQuotaConditionService.genQuotaNumDelay(request.getProjectId(), request.getQuotaId(), null);
        GenQuotaNumResponse.Builder response = GenQuotaNumResponse.newBuilder();
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void createCrossQuota(CreateCrossQuotaRequest request, StreamObserver<CreateCrossQuotaResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now createCrossQuota");
        String projectId = request.getProjectId();
        String quotaId = request.getQuotaId();
        JSONObject param = new JSONObject();
        param.put("project_id", request.getProjectId());
        param.put("quota_id", request.getQuotaId());
        param.put("check_node", request.getCheckNode());
        param.put("ava_qgid_list", request.getAvaQgidList());
        param.put("row1", request.getRow1());
        param.put("row2", request.getRow2());
        param.put("col1", request.getCol1());
        param.put("col2", request.getCol2());
        param.put("checkitem_nums", request.getCheckitemNums());

        surveyQuotaConditionService.createCrossQuotaCondition(projectId, quotaId, param);
        CreateCrossQuotaResponse.Builder response = CreateCrossQuotaResponse.newBuilder();
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void deleteQuotaCondition(DeleteQuotaConditionRequest request, StreamObserver<DeleteResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now deleteQuotaCondition");
        List<String> ids = request.getIdsList();
        DeleteResponse.Builder response = DeleteResponse.newBuilder();
        if (CollectionUtils.isEmpty(ids)) {
            response.setStatus(SUCCESS_STATUS);
            response.setCount(0);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
            return;
        }
        surveyQuotaConditionService.deleteQuotas(ids);
        response.setStatus(SUCCESS_STATUS);
        response.setCount(ids.size());
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void copyQuotaCondition(CopyQuotaConditionRequest request, StreamObserver<CopyQuotaConditionResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now copyQuotaCondition");
        List<String> ids = request.getConditionIdsList();
        String newId = request.getNewId();
        String oldId = request.getOldId();
        CopyQuotaConditionResponse.Builder response = CopyQuotaConditionResponse.newBuilder();
        surveyQuotaConditionService.copyQuota(ids, oldId, newId);
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void copyImportQuotaCondition(CopyImportQuotaConditionRequest request, StreamObserver<CopyImportQuotaConditionResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now copyImportQuotaCondition");
        List<String> ids = request.getConditionIdsList();
        String newQuotaId = request.getNewQuotaId();
        String targetProjectId = request.getTargetProjectId();
        String data = request.getData();
        CopyImportQuotaConditionResponse.Builder response = CopyImportQuotaConditionResponse.newBuilder();
        if (CollectionUtils.isEmpty(ids) || StringUtils.isEmpty(newQuotaId) || StringUtils.isEmpty(targetProjectId)
                || StringUtils.isEmpty(data)) {
            response.setStatus(SUCCESS_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
            return;
        }
        surveyQuotaConditionService.createImportQuota(ids, targetProjectId, newQuotaId, JSONObject.parseObject(data));
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void getQuotaIdList(GetQuotaIdListRequest request, StreamObserver<GetQuotaIdListResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now copyImportQuotaCondition");
        List<String> ids = request.getQgidsList();
        String projectId = request.getProjectId();
        GetQuotaIdListResponse.Builder response = GetQuotaIdListResponse.newBuilder();
        if (CollectionUtils.isEmpty(ids) || StringUtils.isEmpty(projectId)) {
            response.setStatus(SUCCESS_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
            return;
        }
        List<String> quotaIds = surveyQuotaConditionMapper.getQuotaIdList(projectId, ids);
        response.addAllIds(quotaIds);
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void getRespondent(GetRespondentRequest request, StreamObserver<RespondentResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now getRespondent");
        // 获取请求中的id
        String id = request.getId();
        String projectId = request.getProjectId();
        RespondentResponse.Builder response = RespondentResponse.newBuilder();
        if (StringUtils.isEmpty(id)) {
            response.setStatus(SUCCESS_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
            return;
        }
        SurveyRespondent surveyRespondent = surveyRespondentMapper.selectById(id);
        if (surveyRespondent != null) {
            // mysql迁移：获取关联表数据
            SurveyRespondentWeixin weixin = surveyRespondentWeixinMapper.selectOne(new LambdaQueryWrapper<SurveyRespondentWeixin>()
                    .eq(SurveyRespondentWeixin::getRid, surveyRespondent.getId()).last("limit 1"));
            List<SurveyRespondentWeixin> weixins = new ArrayList<>();
            if (weixin != null) {
                weixins.add(weixin);
            }
            surveyRespondent.setWxInfos(weixins);
            List<SurveyRespondentQuotaCheckItem> checkItems = surveyRespondentQuotaCheckItemMapper.selectList(new LambdaQueryWrapper<SurveyRespondentQuotaCheckItem>()
                    .eq(SurveyRespondentQuotaCheckItem::getRid, surveyRespondent.getId()));
            if (CollectionUtils.isEmpty(checkItems)) {
                checkItems = new ArrayList<>();
            }
            surveyRespondent.setQuotaCheckitemList(JSONArray.toJSONString(checkItems));
            response.setRespondent(grpcConvertMapper.toRespondent(surveyRespondent));
        }

        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void updateRespondent(UpdateRespondentRequest request, StreamObserver<UpdateResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now getRespondent");
        // 获取请求中的id,修改答题中的用户id
        String id = request.getId();
        UpdateResponse.Builder response = UpdateResponse.newBuilder();
        if (StringUtils.isEmpty(id)) {
            response.setStatus(FAIL_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
            return;
        }
        Respondent respondent = request.getRespondent();
        LambdaUpdateWrapper<SurveyRespondent> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(SurveyRespondent::getId, id);
        if (StringUtils.isNotEmpty(respondent.getMemberId())) {
            wrapper.set(SurveyRespondent::getMemberId, respondent.getMemberId());
        }
        wrapper.set(SurveyRespondent::getUpdatedDt, LocalDateTime.now());
        surveyRespondentMapper.update(null, wrapper);
        response.setStatus(SUCCESS_STATUS);
        response.setId(id);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void createQuotaCondition(CreateQuotaConditionRequest request, StreamObserver<CreateResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now createQuotaCondition");
        QuotaCondition quotaCondition = request.getQuotaCondition();
        SurveyQuotaCondition condition = grpcConvertMapper.toSurveyQuotaCondition(quotaCondition);
        surveyQuotaConditionMapper.insert(condition);
        CreateResponse.Builder response = CreateResponse.newBuilder();
        response.setId(condition.getId());
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void createQuotaConditionQgidList(CreateQuotaConditionQgidListRequest request, StreamObserver<CreateResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now createQuotaConditionQgidList");
        QuotaConditionQgidList qgidList = request.getQuotaConditionQgidList();
        SurveyQuotaConditionQgidList conditionQgidList = grpcConvertMapper.toSurveyQuotaConditionQgidList(qgidList);
        surveyQuotaConditionQgidListMapper.insert(conditionQgidList);
        CreateResponse.Builder response = CreateResponse.newBuilder();
        response.setId(conditionQgidList.getId());
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void createQuotaCheckItem(CreateQuotaCheckItemRequest request, StreamObserver<CreateResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now createQuotaCheckItem");
        QuotaCheckItem quotaCheckItem = request.getQuotaCheckItem();
        SurveyQuotaCheckItem surveyQuotaCheckItem = grpcConvertMapper.toSurveyQuotaCheckItem(quotaCheckItem);
        // 设置默认值
        surveyQuotaCheckItem.setCurCount(0);
        surveyQuotaCheckItem.setOptionCombies("[]");
        surveyQuotaCheckItemMapper.insert(surveyQuotaCheckItem);
        CreateResponse.Builder response = CreateResponse.newBuilder();
        response.setId(surveyQuotaCheckItem.getId());
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void createQuotaCheckItemOptionCombies(CreateQuotaCheckItemOptionCombiesRequest request, StreamObserver<CreateResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now createQuotaCheckItemOptionCombies");
        QuotaCheckItemOptionCombies optionCombies = request.getQuotaCheckItemOptionCombies();
        SurveyQuotaCheckItemOptionCombies surveyQuotaCheckItem = grpcConvertMapper.toSurveyQuotaCheckItemOptionCombies(optionCombies);
        surveyQuotaCheckItemOptionCombiesMapper.insert(surveyQuotaCheckItem);
        CreateResponse.Builder response = CreateResponse.newBuilder();
        response.setId(surveyQuotaCheckItem.getId());
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void createQuotaCheckItemOptionList(CreateQuotaCheckItemOptionListRequest request, StreamObserver<CreateResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now createQuotaCheckItemOptionList");
        QuotaCheckItemOptionList itemOptionList = request.getQuotaCheckItemOptionList();
        SurveyQuotaCheckItemOptionList optionList = grpcConvertMapper.toSurveyQuotaCheckItemOptionList(itemOptionList);
        surveyQuotaCheckItemOptionListMapper.insert(optionList);
        CreateResponse.Builder response = CreateResponse.newBuilder();
        response.setId(optionList.getId());
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void getColumn(GetColumnRequest request, StreamObserver<ColumnResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now getColumn");
        String id = request.getId();
        SurveyColumn surveyColumn = surveyColumnMapper.selectById(id);
        Column column = grpcConvertMapper.toColumn(surveyColumn);
        ColumnResponse.Builder response = ColumnResponse.newBuilder();
        response.setColumn(column);
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void listRespondent(ListRespondentRequest request, StreamObserver<RespondentSearchResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now listRespondent");
        String search = request.getSearch();
        List<String> fieldsList = request.getFieldsList();
        Respondent respondent = request.getRespondent();
        List<Integer> statusList = request.getStatusList();
        LambdaQueryWrapper<SurveyRespondent> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(respondent.getProjectId())) {
            lambdaQueryWrapper.eq(SurveyRespondent::getProjectId, respondent.getProjectId());
        }
        if (StringUtils.isNotEmpty(respondent.getDeliverId())) {
            lambdaQueryWrapper.eq(SurveyRespondent::getDeliverId, respondent.getDeliverId());
        }
        //查找代码。发现客户端调用只会传递1
        if (ObjectUtil.isNotEmpty(respondent.getStatus().getNumber()) && respondent.getStatus().getNumber() > 0) {
            lambdaQueryWrapper.eq(SurveyRespondent::getStatus, respondent.getStatus().getNumber());
        }
        //查找代码。发现客户端调用只会传递1
        if (ObjectUtil.isNotEmpty(respondent.getDataStatus().getNumber()) && respondent.getDataStatus().getNumber() > 0) {
            lambdaQueryWrapper.eq(SurveyRespondent::getDataStatus, respondent.getDataStatus().getNumber());
        }
        // 调用的地方只设置了againDeliverRecordId
        if (StringUtils.isNotEmpty(respondent.getAgainDeliverRecordId())) {
            lambdaQueryWrapper.eq(SurveyRespondent::getAgainDeliverRecordId, respondent.getAgainDeliverRecordId());
        }
        if (StringUtils.isNotEmpty(respondent.getDlvrRid())) {
            lambdaQueryWrapper.eq(SurveyRespondent::getDlvrRid, respondent.getDlvrRid());
        }
        if (StringUtils.isNotEmpty(respondent.getMemberId())) {
            lambdaQueryWrapper.eq(SurveyRespondent::getMemberId, respondent.getMemberId());
            if (!JSONUtil.isTypeJSONArray(respondent.getMemberId())) {
                lambdaQueryWrapper.eq(SurveyRespondent::getMemberId, respondent.getMemberId());
            } else {
                lambdaQueryWrapper.in(SurveyRespondent::getMemberId, JSONUtil.toList(respondent.getMemberId(), String.class));
            }
        }
        if (StringUtils.isNotEmpty(respondent.getDeliverGroupId())) {
            lambdaQueryWrapper.eq(SurveyRespondent::getDeliverGroupId, respondent.getDeliverGroupId());
        }
        List<SurveyRespondent> surveyRespondents = surveyRespondentMapper.selectList(lambdaQueryWrapper);
        List<Respondent> respondents = new ArrayList<>();
        if (!CollectionUtils.isEmpty(surveyRespondents)) {
            surveyRespondents.forEach(surveyRespondent -> {
                // mysql迁移：获取关联表数据
                SurveyRespondentWeixin weixin = surveyRespondentWeixinMapper.selectOne(new LambdaQueryWrapper<SurveyRespondentWeixin>()
                        .eq(SurveyRespondentWeixin::getRid, surveyRespondent.getId()).last("limit 1"));
                List<SurveyRespondentWeixin> weixins = new ArrayList<>();
                if (weixin != null) {
                    weixins.add(weixin);
                }
                surveyRespondent.setWxInfos(weixins);
                List<SurveyRespondentQuotaCheckItem> checkItems = surveyRespondentQuotaCheckItemMapper.selectList(new LambdaQueryWrapper<SurveyRespondentQuotaCheckItem>()
                        .eq(SurveyRespondentQuotaCheckItem::getRid, surveyRespondent.getId()));
                if (CollectionUtils.isEmpty(checkItems)) {
                    checkItems = new ArrayList<>();
                }
                surveyRespondent.setQuotaCheckitemList(JSONArray.toJSONString(checkItems));
                respondents.add(grpcConvertMapper.toRespondent(surveyRespondent));
            });
        }
        RespondentSearchResponse.Builder response = RespondentSearchResponse.newBuilder();
        response.setStatus(SUCCESS_STATUS);
        response.addAllRespondentList(respondents);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void getQuotaCheckItem(GetQuotaCheckItemRequest request, StreamObserver<QuotaCheckItemResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now getQuotaCheckItem");
        QuotaCheckItemResponse.Builder response = QuotaCheckItemResponse.newBuilder();
        String id = request.getId();
        if (StringUtils.isEmpty(id)) {
            response.setStatus(FAIL_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
            return;
        }
        SurveyQuotaCheckItem quotaCheckItem = surveyQuotaCheckItemMapper.selectById(id);
        if (quotaCheckItem != null) {
            List<SurveyQuotaCheckItemOptionList> optionLists = surveyQuotaCheckItemOptionListMapper.selectList(new LambdaQueryWrapper<SurveyQuotaCheckItemOptionList>()
                    .eq(SurveyQuotaCheckItemOptionList::getQuotaCheckitemId, quotaCheckItem.getId()));
            List<SurveyQuotaCheckItemOptionCombies> optionCombies = surveyQuotaCheckItemOptionCombiesMapper.selectList(new LambdaQueryWrapper<SurveyQuotaCheckItemOptionCombies>()
                    .eq(SurveyQuotaCheckItemOptionCombies::getQuotaCheckitemId, quotaCheckItem.getId()));
            QuotaCheckItem checkItem = grpcConvertMapper.toQuotaCheckItem(quotaCheckItem);
            QuotaCheckItem.Builder itemBuilder = checkItem.toBuilder();
            if (StringUtils.isNotEmpty(quotaCheckItem.getOptionCombies())) {
                itemBuilder.addAllOptionCombies(Arrays.asList(quotaCheckItem.getOptionCombies().split("\\|")));
            }
            if (CollectionUtils.isNotEmpty(optionLists)) {
                itemBuilder.setOptionList(JSONArray.toJSONString(optionLists.stream()
                        .map(SurveyQuotaCheckItemOptionList::getOgid).collect(Collectors.toList())));
            }
            if (CollectionUtils.isNotEmpty(optionCombies)) {
                itemBuilder.setQuotaCheckitemList(JSONArray.toJSONString(optionCombies.stream()
                        .map(SurveyQuotaCheckItemOptionCombies::getId).collect(Collectors.toList())));
            }
            response.setQuotaCheckItem(itemBuilder.build());
        }

        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void getQuotaCondition(GetQuotaConditionRequest request, StreamObserver<QuotaConditionResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now getQuotaCondition");
        QuotaConditionResponse.Builder response = QuotaConditionResponse.newBuilder();
        String id = request.getId();
        if (StringUtils.isEmpty(id)) {
            response.setStatus(FAIL_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
            return;
        }

        List<SurveyQuotaConditionVo> quotaConditionVos = surveyQuotaConditionService.getByIds(Collections.singletonList(id));
        if (CollectionUtils.isNotEmpty(quotaConditionVos)) {
            SurveyQuotaConditionVo conditionVo = quotaConditionVos.get(0);
            QuotaCondition condition = QuotaCondition.newBuilder()
                    .setName(conditionVo.getName())
                    .setId(conditionVo.getId())
                    .setProjectId(conditionVo.getProjectId())
                    .setQuotaId(conditionVo.getQuotaId())
                    .setCheckpoints(conditionVo.getCheckpoints())
                    .setQgidList(JSONArray.toJSONString(conditionVo.getQgidList()))
                    .setQuotaCheckitemList(JSONArray.toJSONString(conditionVo.getQuotaCheckitemList()))
                    .build();
            response.setQuotaCondition(condition);
        }
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void getRespondentData(GetRespondentDataRequest request, StreamObserver<RespondentDataResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now getRespondentData");
        RespondentDataResponse.Builder response = RespondentDataResponse.newBuilder();
        String id = request.getId();
        if (StringUtils.isEmpty(id)) {
            response.setStatus(FAIL_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
            return;
        }
        SurveyRespondentData respondentData = surveyRespondentDataMapper.selectById(id);
        if (respondentData != null) {
            RespondentData toRespondentData = grpcConvertMapper.toRespondentData(respondentData);
            if (StringUtils.isNotEmpty(respondentData.getHashQListKey())) {
                List<SurveyRespondentHashQuestionList> hashQuestionLists = surveyRespondentHashQuestionListMapper
                        .selectList(new LambdaQueryWrapper<SurveyRespondentHashQuestionList>()
                                .eq(SurveyRespondentHashQuestionList::getHashkey, respondentData.getHashQListKey()));
                if (CollectionUtils.isNotEmpty(hashQuestionLists)) {
                    toRespondentData = toRespondentData.toBuilder().setRespondentlistInfo(JSONArray
                            .toJSONString(hashQuestionLists)).build();
                }
            }
            response.setRespondentData(toRespondentData);
        }
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    // 通过查询条件批量一次性获取所有符合条件的ExtParameter
    //rpc ListExtParameter(ListExtParameterRequest) returns (ExtParameterSearchResponse);
    @Override
    public void listExtParameter(ListExtParameterRequest request,
                                 StreamObserver<ExtParameterSearchResponse> responseObserver) {
        ExtParameterSearchResponse.Builder response = ExtParameterSearchResponse.newBuilder();
        try {
            List<SurveyExtParameter> list = surveyExtParameterService.list(
                    new LambdaQueryWrapper<SurveyExtParameter>()
                            .eq(StrUtil.isNotBlank(request.getExtParameter().getProjectId()), SurveyExtParameter::getProjectId, request.getExtParameter().getProjectId())
                            .eq(request.getExtParameter().getVersion() > 0, SurveyExtParameter::getVersion, request.getExtParameter().getVersion())
            );

            response.setStatus(SUCCESS_STATUS);
            response.addAllExtParameterList(grpcConvertMapper.toExtParameterList(list));
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
        } catch (Exception e) {
            log.error("[Survey] listExtParameter error", e);
            response.setStatus(FAIL_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
        }
    }


    @Override
    public void copyExtParameter(CopyExtParameterRequest request,
                                 StreamObserver<CopyExtParameterResponse> responseObserver) {
        String id = new ObjectId().toHexString();
        CopyExtParameterResponse.Builder response = CopyExtParameterResponse.newBuilder();
        try {
            SurveyExtParameter old_ext_param = surveyExtParameterService.getExtParam(request.getProjectId(), String.valueOf(request.getReleaseVer() - 1), Boolean.FALSE);
            String data = "[]";
            String aes_key = RandomStringUtils.randomAscii(16);
            if (Objects.nonNull(old_ext_param)) {
                data = old_ext_param.getData();
                aes_key = old_ext_param.getAesKey();
            }

            SurveyExtParameter insert = new SurveyExtParameter();
            insert.setId(id);
            insert.setProjectId(request.getProjectId());
            insert.setVersion(request.getReleaseVer());
            insert.setData(data);
            insert.setAesKey(aes_key);
            if (Objects.nonNull(old_ext_param) && StrUtil.isNotEmpty(old_ext_param.getSecret())) {
                insert.setSecret(old_ext_param.getSecret());
            }
            surveyExtParameterService.save(insert);
        } catch (Exception e) {
            log.error("[Survey] copyExtParameter error", e);
            response.setStatus(FAIL_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
            return;
        }

        response.setStatus(SUCCESS_STATUS);
        response.setExtId(id);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void createColumnsRelsProject(CreateColumnsRelsProjectRequest request,
                                         StreamObserver<CreateColumnsRelsProjectResponse> responseObserver) {
        CreateColumnsRelsProjectResponse.Builder response = CreateColumnsRelsProjectResponse.newBuilder();
        try {
            surveyMessageReceiverService.createColumnsRelsproject(request.getProjectId(), "", request.getCompanyId());
        } catch (Exception e) {
            log.error("【Survey】createColumnsRelsProject error", e);
            response.setStatus(FAIL_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
            return;
        }
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void getDeliverRspdAmount(GetDeliverRspdAmountRequest request, StreamObserver<GetDeliverRspdAmountResponse> responseObserver) {
        GetDeliverRspdAmountResponse.Builder response = GetDeliverRspdAmountResponse.newBuilder();
        log.info("Now to getDeliverRspdStatus");
        String deliverId = request.getDeliverId();
        String memberId = request.getMemberId();
        Integer status = StringUtils.isEmpty(request.getStatus()) ? null : Integer.parseInt(request.getStatus());
        String projectId = request.getProjectId();
        String groupId = request.getGroupId();
        List<String> groupIdList = CollectionUtils.isEmpty(request.getGroupIdListList()) ? new ArrayList<>()
                : new ArrayList<>(request.getGroupIdListList());
        List<String> dedCodeList = CollectionUtils.isEmpty(request.getDedCodeListList()) ? new ArrayList<>()
                : new ArrayList<>(request.getDedCodeListList());
        try {
            response.setAmount(Integer.parseInt(surveyRespondentService.getDeliverRspdAmount(deliverId, groupId, groupIdList, memberId,
                    status, dedCodeList, projectId).toString()));
        } catch (Exception e) {
            log.error("[Survey] getDeliverRspdAmount error", e);
            response.setStatus(FAIL_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
            return;
        }
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    @Override
    public void getDeliverRspdStatus(GetDeliverRspdStatusRequest request, StreamObserver<GetDeliverRspdStatusResponse> responseObserver) {
        GetDeliverRspdStatusResponse.Builder response = GetDeliverRspdStatusResponse.newBuilder();
        log.info("Now to getDeliverRspdStatus");
        String deliverId = request.getDeliverId();
        String memberId = request.getMemberId();
        String dedCode = request.getDedCode();
        Integer status = StringUtils.isEmpty(request.getStatus()) ? null : Integer.parseInt(request.getStatus());
        String projectId = request.getProjectId();
        try {
            response.setState(surveyRespondentService.getDeliverRspdStatus(deliverId, memberId, dedCode, status, projectId));
        } catch (Exception e) {
            log.error("[Survey] getDeliverRspdStatus error", e);
            response.setStatus(FAIL_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
            return;
        }
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    //rpc GetRespondentAmountBatch(GetRespondentAmountBatchRequest) returns (GetRespondentAmountBatchResponse);
    @Override
    public void getRespondentAmountBatch(GetRespondentAmountBatchRequest request, StreamObserver<GetRespondentAmountBatchResponse> responseObserver) {
        GetRespondentAmountBatchResponse.Builder response = GetRespondentAmountBatchResponse.newBuilder();
        try {
            //select member_id,count(1) as count  from  survey_respondent
            //where member_id in('6035f157c238850024dbc9d5') group by member_id;
            QueryWrapper<SurveyRespondent> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("member_id,count(1) as count");
            if (StrUtil.isNotBlank(request.getProjectId())) {
                queryWrapper.eq("project_id", request.getProjectId());
            }
            if (StrUtil.isNotBlank(request.getDeliverId())) {
                queryWrapper.eq("deliver_id", request.getDeliverId());
            }
            if (request.getStatus() > 0) {
                queryWrapper.eq("status", request.getStatus());
            }
            if (!org.springframework.util.CollectionUtils.isEmpty(request.getMemberIdList())) {
                queryWrapper.in("member_id", request.getMemberIdList());
            }

            queryWrapper.groupBy("member_id");
            List<Map<String, Object>> dbDatas = surveyRespondentMapper.selectMaps(queryWrapper);
            List<GetRespondentAmountBatchItem> list = new ArrayList<>();
            dbDatas.forEach(it -> {
                GetRespondentAmountBatchItem.Builder item = GetRespondentAmountBatchItem.newBuilder();
                item.setMemberId(it.get("member_id").toString());
                item.setCount(Integer.parseInt(it.get("count").toString()));
                list.add(item.build());
            });
            response.addAllRespondent(list);
            response.setStatus(SUCCESS_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
        } catch (Exception e) {
            log.error("[Survey] getRespondentAmountBatch error", e);
            response.setStatus(FAIL_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
        }
    }

    //rpc GetRespondentStatusBatch(GetRespondentStatusBatchRequest) returns (GetRespondentStatusBatchResponse);
    @Override
    public void getRespondentStatusBatch(GetRespondentStatusBatchRequest request, StreamObserver<GetRespondentStatusBatchResponse> responseObserver) {
        GetRespondentStatusBatchResponse.Builder response = GetRespondentStatusBatchResponse.newBuilder();
        try {
            QueryWrapper<SurveyRespondent> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("status, member_id, id");
            if (StrUtil.isNotBlank(request.getProjectId())) {
                queryWrapper.eq("project_id", request.getProjectId());
            }
            if (StrUtil.isNotBlank(request.getDeliverId())) {
                queryWrapper.eq("deliver_id", request.getDeliverId());
            }
            if (request.getStatus() > 0) {
                queryWrapper.eq("status", request.getStatus());
            }
            if (!org.springframework.util.CollectionUtils.isEmpty(request.getMemberIdList())) {
                queryWrapper.in("member_id", request.getMemberIdList());
            }

            List<Map<String, Object>> dbDatas = surveyRespondentMapper.selectMaps(queryWrapper);
            List<GetRespondentStatusBatchResponseItem> list = new ArrayList<>();
            dbDatas.forEach(it -> {
                GetRespondentStatusBatchResponseItem.Builder item = GetRespondentStatusBatchResponseItem.newBuilder();
                item.setMemberId(it.get("member_id").toString());
                item.setStatus(Integer.parseInt(it.get("status").toString()));
                item.setId(it.get("id").toString());
                list.add(item.build());
            });
            response.addAllRespondent(list);
            response.setStatus(SUCCESS_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
        } catch (Exception e) {
            log.error("[Survey] getRespondentStatusBatch error", e);
            response.setStatus(FAIL_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
        }
    }

    //rpc GetFinishedAllMemberIds(GetFinishedAllMemberIdsRequest) returns (GetFinishedAllMemberIdsResponse);
    @Override
    public void getFinishedAllMemberIds(GetFinishedAllMemberIdsRequest request, StreamObserver<GetFinishedAllMemberIdsResponse> responseObserver) {
        log.info("[Survey] getFinishedAllMemberIds projectId={},fromTs={},toTs={}", request.getProjectId(), request.getFromTs(), request.getToTs());
        GetFinishedAllMemberIdsResponse.Builder response = GetFinishedAllMemberIdsResponse.newBuilder();
        try {
            LambdaQueryWrapper<SurveyRespondent> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.isNotNull(SurveyRespondent::getMemberId);
            queryWrapper.ne(SurveyRespondent::getMemberId, "''");
            queryWrapper.ne(SurveyRespondent::getMemberId, "'null'");
            queryWrapper.eq(SurveyRespondent::getProjectId, request.getProjectId());
            queryWrapper.eq(SurveyRespondent::getDataStatus, RESPONDENT_DATA_STATUS_FORMAL_VALUE);
            queryWrapper.eq(SurveyRespondent::getStatus, RESPONDENT_STATUS_FINISH_VALUE);
            queryWrapper.ge(SurveyRespondent::getFinishTime, LocalDateTimeUtil.of(request.getFromTs()));
            queryWrapper.le(SurveyRespondent::getFinishTime, LocalDateTimeUtil.of(request.getToTs()));
            List<SurveyRespondent> surveyRespondents = surveyRespondentMapper.selectList(queryWrapper);
            List<String> list = surveyRespondents.stream()
                    .map(SurveyRespondent::getMemberId)
                    .filter(StrUtil::isNotEmpty)
                    .collect(Collectors.toList());
            response.addAllMemberId(ObjectUtils.isEmpty(list) ? new ArrayList<>() : list);
            response.setStatus(SUCCESS_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
        } catch (Exception e) {
            log.error("[Survey] getFinishedAllMemberIds error", e);
            response.setStatus(FAIL_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
        }
    }

    // 根据 指定时间获取问卷的 答卷数量,BI用
    //rpc GetRspdCountForBiShareByTimeRange(GetRspdCountForBiShareByTimeRangeRequest) returns (GetRspdCountForBiShareByTimeRangeResponse);
    @Override
    public void getRspdCountForBiShareByTimeRange(GetRspdCountForBiShareByTimeRangeRequest request,
                                                  StreamObserver<GetRspdCountForBiShareByTimeRangeResponse> responseObserver) {
        log.info("[BaseSurveyGrpcService] now getRspdCountForBiShareByTimeRange");
        GetRspdCountForBiShareByTimeRangeResponse.Builder response = GetRspdCountForBiShareByTimeRangeResponse.newBuilder();

        String projectId = request.getProjectId();
        Timestamp startTime = request.getStartTime();
        Timestamp endTime = request.getEndTime();
        if (StringUtils.isEmpty(projectId) || startTime.getSeconds() < 0
                || endTime.getSeconds() < 0) {
            response.setStatus(FAIL_STATUS);
            responseObserver.onNext(response.build());
            responseObserver.onCompleted();
            return;
        }

        // 获取指定范围内的有效答卷数的数量
        Long count = surveyRespondentMapper.selectCount(new LambdaQueryWrapper<SurveyRespondent>()
                .eq(SurveyRespondent::getProjectId, projectId)
                .eq(SurveyRespondent::getDataStatus, RESPONDENT_DATA_STATUS_FORMAL_VALUE)
                .in(SurveyRespondent::getSource, RESPONDENT_FORMAL_SOURCE)
                .in(SurveyRespondent::getStatus,
                        Lists.newArrayList(RESPONDENT_STATUS_BEGIN.getValue(),
                                RESPONDENT_STATUS_FINISH.getValue(),
                                RESPONDENT_STATUS_UNFINISH.getValue(),
                                RESPONDENT_STATUS_SCREEN_OUT.getValue(),
                                RESPONDENT_STATUS_QUOTA_FULL.getValue(),
                                RESPONDENT_STATUS_BACKUP.getValue())
                )
                .ge(SurveyRespondent::getBeginTime, googleTimestampToLocalDateTime(startTime))
                .lt(SurveyRespondent::getBeginTime, googleTimestampToLocalDateTime(endTime)));

        response.setCount(Integer.parseInt(String.valueOf(count)));
        response.setStatus(SUCCESS_STATUS);
        responseObserver.onNext(response.build());
        responseObserver.onCompleted();
    }

    private LocalDateTime googleTimestampToLocalDateTime(Timestamp timestamp) {
        if (timestamp == null || timestamp.getSeconds() < 0) {
            return null;
        }
        Date date = new Date(timestamp.getSeconds() * 1000);
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDateTime();
    }
}